package com.mc.main;

import android.content.Context;
import android.content.res.Resources;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Point;
import android.graphics.Paint.Cap;
import android.os.Handler;
import android.os.Message;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;

/**
 * Draws a simple graph, uses a helper class to poll a
 * sensor for new values
 * 
 * @author Mikael Bertlin
 *
 */

public class SimpleGraphView extends View implements SensorEventListener{
	
	
	public int fulTemp = 0;
	private static GraphHelper myHelper;
	private MyLittleFriend mlf;
	private static final String TAG = "SimpleGraphView";
	private Paint fingerLinePaint;
	private Paint graphGridPaintThickLight;
	private Paint graphLinePaint;
	private Paint simpleTextPaint;
	private Paint simpleTextBoxPaint;
	private static final int MAXY = 290;
	private float cx = 0;
	private float cy = 290;
	private boolean drawFingerLine = false;
	private Point[] pArr;
	private int width = 310;
	private int time = 0;
	private int oldTime = 0;
	private Handler handler;
	private int points = 29;
	
	Resources res = this.getContext().getResources();
	
	public SimpleGraphView(Context context, AttributeSet attrs) {
		
		super(context, attrs);
        setFocusable(true);
    	setFocusableInTouchMode(true);

    	/**
    	 * Seems like I can't invalidate this view from MyLittleHelper
    	 * via SensorEventReceived so I need this ...
    	 */
    	
		handler = new Handler() {
	        @Override
	        public void handleMessage(Message msg) {
	            invalidate();
	        }
	    };
    	
		myHelper = new GraphHelper();
		mlf = new MyLittleFriend(handler);
		mlf.addListener(this);
		mlf.pollOn();
		mlf.go();
		
		int fingerLine = res.getColor(R.color.simpleFingerLine);
		fingerLinePaint = new Paint();
		fingerLinePaint.setAntiAlias(true);
		fingerLinePaint.setColor(fingerLine);
		fingerLinePaint.setTextSize(20);
		fingerLinePaint.setStrokeWidth(1);
		
		int fingerLineLight = res.getColor(R.color.simpleFingerLineLighter);
        graphGridPaintThickLight = new Paint();
        graphGridPaintThickLight.setColor(fingerLineLight);
        graphGridPaintThickLight.setStrokeWidth(2);
		
		int graphLine = res.getColor(R.color.simpleGraphLine);
		graphLinePaint = new Paint();
		graphLinePaint.setAntiAlias(true);
		graphLinePaint.setColor(graphLine);
		graphLinePaint.setStrokeCap(Cap.ROUND);
		graphLinePaint.setStrokeWidth(5);
		
		int simpleText = res.getColor(R.color.simpleText);
		simpleTextPaint = new Paint();
		simpleTextPaint.setAntiAlias(true);
		simpleTextPaint.setColor(simpleText);
		simpleTextPaint.setTextSize(22);
		simpleTextPaint.setStrokeWidth(3);
		
		int simpleTextBox = res.getColor(R.color.simpleTextBox);
		simpleTextBoxPaint = new Paint();
		simpleTextBoxPaint.setAntiAlias(true);
		simpleTextBoxPaint.setColor(simpleTextBox);
		simpleTextBoxPaint.setTextSize(22);
		simpleTextBoxPaint.setStrokeWidth(3);
	}
	@Override
	protected void onSizeChanged(int w, int h, int oldw, int oldh) {
		// TODO: How to save the graph?
		super.onSizeChanged(w, h, oldw, oldh);
		width = w - 10;
		if(w == 320)
			points = 28;
		else 
			points = 42;
	}

    protected void onDraw(Canvas canvas) {
    	float temp = 290 - cy;
    	//Where you point I draw!
    	if(drawFingerLine){
    		if(!myHelper.isEmpty()){
        		//Draw this from the right to the left
   			 	graphLinePaint.setStrokeWidth(10);
   				int focus = res.getColor(R.color.simpleGraphLineFocus);
   				graphLinePaint.setColor(focus);
        		Point nullP = new Point(0,0);
        		time = 0;
        		oldTime = 0;
        		
        		pArr = myHelper.getLastPoints(points);
        		for(int i = 0;i < pArr.length; i++){
        			time += 10; //100 points ... times 10 = 300
        			if(pArr[i] != null){
          				if(nullP.y >= 0 && pArr[i].y >= 0){
          					canvas.drawLine(oldTime, MAXY - nullP.y, time, MAXY - pArr[i].y, graphLinePaint);
          				}
        				nullP = pArr[i];
        			}
        			oldTime = time;
        		}
        	}
    	}

    	if(!myHelper.isEmpty()){
    		//Draw this from the right to the left
    		Point nullP = new Point(0,0);
    		graphLinePaint.setStrokeWidth(5);
    		int normal = res.getColor(R.color.simpleGraphLine);
			graphLinePaint.setColor(normal);
    		time = 0;
    		oldTime = 0;
    		pArr = myHelper.getLastPoints(points);
    		for(int i = 0;i < pArr.length; i++){
    			time += 10; //100 points ... times 10 = 300
    			if(pArr[i] != null){
    				if(nullP.y >= 0 && pArr[i].y >= 0){
    					canvas.drawLine(oldTime, MAXY - nullP.y, time, MAXY - pArr[i].y, graphLinePaint);
      				}
    				nullP = pArr[i];
    			}
    			oldTime = time;
    		}
    	}
		if(drawFingerLine){
    		
    		canvas.drawLine(cx-1, 92, cx-1, 286,graphGridPaintThickLight);	
    		canvas.drawLine(cx+1, 92, cx+1, 286,graphGridPaintThickLight);
    		canvas.drawLine(cx, 92, cx, 286,fingerLinePaint);
    		canvas.drawCircle(cx, cy, 9, fingerLinePaint);
    		canvas.drawCircle(cx, cy, 6, graphGridPaintThickLight);
    		
    		if(cx < (width / 2)){
    			canvas.drawRect(cx + 4, 90, cx + 134, 120, simpleTextBoxPaint);
    			canvas.drawRect(cx + 8, 94, cx + 130, 116, graphLinePaint);
    			canvas.drawText("Temp: " + temp, cx + 8, 112, simpleTextPaint);
    		} else {
    			canvas.drawRect(cx - 134, 90, cx - 4, 120, simpleTextBoxPaint);
    			canvas.drawRect(cx - 130, 94, cx - 8, 116, graphLinePaint);
    			canvas.drawText("Temp: " + temp, cx - 130, 112, simpleTextPaint);
    			
    		}
    		
		}

    }

    public void SensorEventReceived(SensorEvent evt) {
		Point p = new Point();
		p.set(evt.getTime(), evt.getValue());
		myHelper.addPoint(p);
	}
    
    public void littleFriendOn(){
    	mlf.pollOn();
    	mlf.go();
    }
    
    public void littleFriendOff(){
    	mlf.pollOff();
    }
    
	public synchronized boolean onTouchEvent(MotionEvent event) {
		
		if(event.getAction() == MotionEvent.ACTION_DOWN){
			 Log.v(TAG, "DOWN");
			 drawFingerLine = true;
			 mlf.pollOff();
			 this.invalidate(); //Redraw please!
			 return true;
		} else if(event.getAction() == MotionEvent.ACTION_UP){
			 Log.v(TAG, "UP");
			 graphLinePaint.setStrokeWidth(4);
			 drawFingerLine = false;
			 //mlf = new MyLittleFriend(handler);
			 mlf.addListener(this);
			 mlf.pollOn();
			 mlf.go();
			 this.invalidate(); //Redraw please!
			 return true;
		} else if(event.getAction() == MotionEvent.ACTION_MOVE){
			int soFar = time / 10;
			pArr = myHelper.getLastPoints(soFar);
			int index = (int) (event.getX() / 10);
			if((index < soFar) && (index < pArr.length) && (index >= 0)){
				cy = 290 - (float)pArr[index].y;
				cx = event.getX();
			}
			Log.v(TAG, "x:" + cx + "y: " + cy + "index: " + index);
			if((int)cx >= (width - 20))
				cx = width;
			if((int)cx <= 10)
				cx = 10;
			this.invalidate(); //Redraw please!
			return true;
		}
		return false;
	}
}

/**
 * Helper class that runs in its own thread polling a sensor
 * 
 * @author Mikael Bertlin
 *
 */

class  MyLittleFriend implements Runnable{
	
	private UnitAccessDummy myAccess;
	private UdpClient client;
	private SensorEventListener sel;
	private static final int RES = 1000; //Update speed, less is more
	private static final String TAG = "MyLittleFriend";
	private Thread myThread = null;
	private boolean polling = false;
	private Handler handler;
	
	public MyLittleFriend(Handler handler){
		this.handler = handler;
	}
	
	public void addListener(SensorEventListener sel){
		this.sel =  sel;
	}
		
	public void go(){
		if(myThread == null) {
			myThread = new Thread(this);
			myThread.start();
			
			

		}
	}
	
	public void pollOn(){
		polling = true;
		Log.v(TAG, "Polling on!");
	}
	
	public void pollOff(){
		polling = false;
		Log.v(TAG, "Polling off!");

	}
	
	public void run() {
		
		client = UdpClient.client;
		myAccess = new UnitAccessDummy(client);
		client.addUdpEventListener(myAccess);
		client.startListen();

		
		//Only oone thread please!
		while(true){
			if(polling){
				//Log.v(TAG, "Polling");
				Log.v("Polling", String.valueOf(myAccess.getTemp()));
				try{
					Thread.currentThread().sleep(RES);
				}
					catch(InterruptedException ie){
						Log.v(TAG, "ie");
					}
					//Read temp trigger event, tell listeners
					sel.SensorEventReceived(new SensorEvent(this, myAccess.getTemp()));
					handler.sendEmptyMessage(0);
			}
		}
	}
}
